package com.zzl.bonds.ticket.manager;

import com.alibaba.fastjson.JSON;
import com.rabbitmq.client.Channel;
import com.zzl.bonds.ticket.conf.RabbitMqConf;
import com.zzl.bonds.ticket.service.*;
import com.zzl.general.common.exception.SysException;
import com.zzl.general.common.system.dto.MQCallbackDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;

/**
 * Mq任务 监听类
 *
 * @author : spp
 * @date : 2022/1/19 10:37
 */
@Component
@Slf4j
public class MqManager {


    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private TicketOpenService ticketOpenService;

    @Autowired
    private TicketTransferService ticketTransferService;

    @Autowired
    private TicketFinanceService ticketFinanceService;

    @Autowired
    private TicketService ticketService;

    @Autowired
    private CoreEnterpriseCreditService coreEnterpriseCreditService;

    /**
     * 监听 预兑付回滚的 任务队列
     *
     * @param message     消息体
     * @param deliveryTag head 发送参数
     * @param channel     通道连接
     */
    @RabbitListener(queues = RabbitMqConf.ADVANCE_PAYMENT_QUEUE)
    public void listenAdvancePayment(@Payload Message message, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag, Channel channel) {
        MQCallbackDto callbackDto = new MQCallbackDto();
        callbackDto.setEndTime(new Date());
        try {
            Integer days = setJobId(message, callbackDto);
            if (ObjectUtils.isEmpty(days)) {
                throw new SysException("传入参数错误:无时间参数");
            }
            ticketService.executeWaitingPayment(days);
            ticketOpenService.executeWaitingPayment(days);
            ticketTransferService.executeWaitingPayment(days);
            ticketFinanceService.executeWaitingPayment(days);
            callbackDto.setExecutionLog("正常执行");
            callbackDto.setStatus(2);
        } catch (Exception e) {
            // 当方法报错时一样确认消费消息
            callbackDto.setStatus(1);
            callbackDto.setExecutionLog(e.getMessage());
            log.error(e.getMessage());
        } finally {
            rabbitTemplate.convertAndSend(RabbitMqConf.SYSTEM_EXCHANGE, RabbitMqConf.TASK_CALLBACK, JSON.toJSONString(callbackDto));
            log.info("=============================回调定时任务信息{}=====================", callbackDto);
        }
    }

    /**
     * 处理 核心企业授信额度状态的 任务队列，每天凌晨执行一次
     * 备注：如果数据是 凌晨2点同步，则，在代码逻辑中新增（后续优化）
     *
     * @param message     小心体
     * @param deliveryTag hand 发送参数
     * @param channel     通道
     */
    @RabbitListener(queues = RabbitMqConf.CREDIT_STATUS_QUEUE)
    public void handCreditStatus(@Payload Message message, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag, Channel channel) throws SysException {
        try {
            coreEnterpriseCreditService.handCreditStatus();
        } catch (Exception e) {
            log.info("更新授信额度状态数据错误{}", e.getMessage());
            throw new SysException("更新授信额度状态数据错误");
        }
    }

    /**
     * 设置 objId
     *
     * @param message     信息
     * @param callbackDto 返回参数
     * @return 天数
     */
    private Integer setJobId(Message message, MQCallbackDto callbackDto) {
        String msg = new String(message.getBody(), StandardCharsets.UTF_8);
        log.info("================定时任务输入参数{}", msg);
        Map<String, Object> map = JSON.parseObject(msg, Map.class);
        callbackDto.setMJobExecutionRecordId((Integer) map.get("mJobExecutionRecordId"));
        return (Integer) map.get("days");
    }
}
